import re
import time
import asyncio
from queue import Queue
from threading import Thread

import botpy
from botpy import logging
from botpy.user import Member
from botpy.message import Message

from src.utils.method import Method
from src.conf.conf_manager import ConfManager
from src.logger import Logger


class Handler(botpy.Client):
    def __init__(self, conf: ConfManager, logger: Logger):
        """处理与机器人的ws连接"""
        intents = botpy.Intents.none()
        intents.public_guild_messages = True
        intents.guild_members = True
        super().__init__(intents)
        logging.get_logger().setLevel(40)
        # 内部参数
        self.alive = False
        self.__conf = conf
        self.__logger = logger
        self.last_msg_time = 0
        self.event = Queue()
        self.member_id_list = []
        self.admin_id_list = []
        self.guild_id = self.__conf.robot_conf.group
        self.owners = self.__conf.robot_conf.owners

    async def on_ready(self):
        self.alive = True
        # 维护内部成员列表与管理员列表
        while True:
            await asyncio.sleep(5)
            if not self.guild_id:
                continue
            member_list = await self.api.get_guild_members(self.guild_id, limit=1000)
            if not member_list:
                continue
            if len(member_list) >= 1000:
                self.__logger.add_log("[DLS][WARN] 群组人数过多, 无法获取成员列表, 请联系开发者")
            self.member_id_list.clear()
            for member in member_list:
                self.member_id_list.append(member["user"]["id"])
                # 确认身份组 2:管理员 4:创建者
                roles: list = member["roles"]
                for role in roles:
                    if role in ["2", "4"]:
                        self.admin_id_list.append(member["user"]["id"])
                        break

    async def on_at_message_create(self, message: Message):
        # 保存最后消息时间，用于确定机器人可持续回复的时间
        this_msg_time = time.time()
        # 去除@部分与/开头
        text: str = re.sub("<@.+> ", "", message.content, 1)
        if re.match("/", text):
            text = text.replace("/", "", 1)
        # ID查询与注册机器人
        if re.match("查询ID", text):
            back_id = message.author.id
            plain = text.replace("查询ID", "", 1).strip()
            res = re.search("(?<=<@!).+?(?=>)", plain)
            if res:
                back_id = res.group()
            await message.reply(content=f"用户ID: {back_id}\n"
                                        f"频道ID: {message.guild_id}")
        elif text == "注册机器人":
            if message.author.id in self.owners:
                self.reset_guild_id(message.guild_id)
                await message.reply(content="成功注册到此群组")
        # 忽略其他频道消息
        if message.guild_id != self.guild_id:
            return
        # 生成便于处理的字典并储存
        message.content = Method.deal_at_tags(text)
        self.event.put({"type": "message", "data": message})
        # 准备回复日志消息
        self.last_msg_time = this_msg_time
        while True:
            # 若不是最新的消息，跳出
            if self.last_msg_time != this_msg_time:
                break
            # 当超过5分钟时，跳出
            if time.time() - this_msg_time > 299:
                await message.reply(content=f"回复时间结束")
                break
            combine_msg = self.__logger.get_robot_msg()
            if combine_msg.length:
                await message.reply(content=f"{combine_msg.text}")
            await asyncio.sleep(0.2)

    async def on_guild_member_remove(self, member: Member):
        # 只识别指定群组的退群消息
        if member.guild_id == self.guild_id:
            self.event.put({"type": "member_remove", "member": member})

    def reset_guild_id(self, guild_id: str):
        """重设并保存群组ID"""
        self.guild_id = guild_id
        self.__conf.robot_conf.group = guild_id
        self.__conf.robot_conf.save()

    def connect(self):
        """连接机器人"""
        while True:
            try:
                self.run(self.__conf.robot_conf.app_id,
                         self.__conf.robot_conf.secret)
            except Exception as e:
                self.__logger.add_log(f"[DLS][WARN] 机器人连接失败或中断: {e}")
            self.alive = False
            break

    def reload(self):
        self.guild_id = self.__conf.robot_conf.group
        self.owners = self.__conf.robot_conf.owners

    def auto_run(self):
        Thread(target=self.connect, daemon=True).start()
